package org.xx.armory.swing.components;

import org.xx.armory.swing.UIController;

import javax.swing.*;
import java.awt.Component;
import java.awt.Container;
import java.awt.Image;

import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.Validators.notNull;

/**
 * 面板的抽象基类。
 *
 * @param <O>
 *         包含面板的容器类型，比如{@link JDialog}等。
 */
public abstract class AbstractPane<O extends Component & RootPaneContainer>
        extends JPanel {
    private O owner;
    private UIController uiController;
    private String title;
    private Image icon;
    private JButton defaultButton;

    /**
     * 构造抽象面板基类，所有者和UI控制器都被初始化{@code null}。
     */
    protected AbstractPane() {
        this.owner = null;
        this.uiController = null;
        this.title = "";
        this.icon = null;
        this.defaultButton = null;

        initUi();
    }

    /**
     * 通过UI控制器初始化UI。
     */
    protected final void initUi() {
        this.uiController = createUIController();
        this.uiController.load();
    }

    /**
     * 创建此面板使用的UI控制器。
     *
     * @return 此面板使用的UI控制器。
     */
    protected abstract UIController createUIController();

    /**
     * 获取此面板关联的UI控制器。
     *
     * @return 此面板关联的UI控制器。
     */
    public final UIController controller() {
        return this.uiController;
    }

    /**
     * 获取面板的标题。
     *
     * @return 面板的标题。
     */
    public final String getTitle() {
        return this.title;
    }

    /**
     * 设置面板的标题。
     *
     * @param title
     *         面板标题，自动去掉首尾空格。
     */
    public final void setTitle(
            String title
    ) {
        final String oldTitle = this.title;
        this.title = trimToEmpty(title);

        firePropertyChange("title", oldTitle, this.title);
    }

    /**
     * 获取面板的图标。
     *
     * @return 面板的图标。
     */
    public final Image getIcon() {
        return this.icon;
    }

    /**
     * 设置面板的图标。
     *
     * @param icon
     *         面板的图标，{@code null}表示不显示图标。
     */
    public final void setIcon(
            Image icon
    ) {
        final Image oldIcon = this.icon;
        this.icon = icon;

        firePropertyChange("icon", oldIcon, this.icon);
    }

    /**
     * 获取面板的默认按钮。
     *
     * @return 面板的默认按钮。
     */
    public final JButton getDefaultButton() {
        return this.defaultButton;
    }

    /**
     * 设置面板的默认按钮。
     *
     * @param defaultButton
     *         面板的默认按钮，{@code null}表示没有默认按钮。
     */
    public final void setDefaultButton(
            JButton defaultButton
    ) {
        final JButton oldDefaultButton = this.defaultButton;
        this.defaultButton = defaultButton;

        firePropertyChange("defaultButton", oldDefaultButton, this.defaultButton);
    }

    /**
     * 获取面板的所有者。
     *
     * @return 面板的所有者。
     */
    public final O getOwner() {
        return this.owner;
    }

    /**
     * 设置面板的所有者。
     * <p>设置所有者之后，此面板被设置为所有者的内容面板。</p>
     * <p>如果此面板之前已有所有者，那么原所有者的内容面板被设置为空的JLabel。</p>
     *
     * @param owner
     *         面板的所有者。
     * @throws IllegalArgumentException
     *         如果参数{@code owner}是{@code null}。
     * @see RootPaneContainer#setContentPane(Container)
     */
    public final void setOwner(
            O owner
    ) {
        notNull(owner, "owner");

        if (this.owner == owner) {
            return;
        }

        if (this.owner != null) {
            this.owner.setContentPane(new JLabel("content was removed"));
        }

        final O oldOwner = this.owner;
        this.owner = owner;
        this.owner.setContentPane(this);

        firePropertyChange("owner", oldOwner, this.owner);
    }

//    /**
//     * 显示异常。
//     *
//     * @param throwable
//     *         待显示的异常。
//     */
//    protected void error(
//            Throwable throwable
//    ) {
//        if (throwable == null) {
//            return;
//        }
//
//        try (final StringWriter writer = new StringWriter()) {
//            throwable.printStackTrace(new PrintWriter(writer));
//            writer.flush();
//            DialogUtils.fail(this.getOwner(), "<html><pre>" + writer + "</pre></html>");
//        } catch (Exception ignore) {
//        }
//    }
}
